﻿namespace BM.Tools.WebControls.MForm.Controls.Helper
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web.UI;    

    /// <summary>
    /// A class that helps with prototype data creation.
    /// Prototypes are needed for dynamic items addition on the client side.
    /// </summary>
    internal class PrototypeDataHelper
    {
        private List<string> namesList;
        private List<List<string>> clientIdParts;

        /// <summary>
        /// Initializes a new instance of the <see cref="PrototypeDataHelper"/> class.
        /// </summary>
        /// <param name="offspring">
        /// The offspring.
        /// </param>
        public PrototypeDataHelper(Offspring offspring)
        {
            Owner = offspring;
        }

        /// <summary>
        /// Gets the owner offspring.
        /// </summary>
        public Offspring Owner
        { 
            get; 
            private set;
        }

        /// <summary>
        /// Gets teh id separator o  the page.
        /// </summary>
        public char IdSeparator
        {
            get
            {
                return Owner.Page.IdSeparator;
            }
        }

        /// <summary>
        /// Gets the root of the MForm tree.
        /// </summary>
        public Root Root
        {
            get
            {
                return Owner.Root;                
            }            
        }

        /// <summary>
        /// Gets a ScriptComponentDescriptor of a prototype associated with this offspring.
        /// </summary>
        public ScriptComponentDescriptor PrototypeDescriptor
        {
            get
            {
                EnsurePrototypeDescriptor();
                return Root.PrototypeDescriptors[NamesListKey];
            }
        }

        private string UniqueId
        {
            get
            {
                return string.Join(string.Concat(IdSeparator, "0", IdSeparator), ClientIdParts.Select(list => string.Join(IdSeparator.ToString(), list.ToArray())).ToArray()) + IdSeparator + "0";
            }
        }

        private string ClientId
        {
            get
            {
                return string.Join("_0_", ClientIdParts.Select(list => string.Join("_", list.ToArray())).ToArray())  + "_0";
            }
        }

        private List<string> NamesList
        {
            get
            {
                if (namesList == null)
                {
                    namesList = new List<string>();
                    var currentOffspring = Owner;
                    while (currentOffspring != null)
                    {
                        namesList.Insert(0, currentOffspring.ID);
                        currentOffspring = currentOffspring.ParentBasis;
                    }                    
                }
                
                return namesList;
            }
        }

        private List<List<string>> ClientIdParts
        {
            get
            {
                if (clientIdParts == null)
                {
                    clientIdParts = new List<List<string>>();
                    var currentOffspring = Owner;
                    while (currentOffspring != null)
                    {
                        var parentOffspring = currentOffspring.ParentBasis;
                        string idIncrement;
                        
                        if (parentOffspring == null)
                        {
                            idIncrement = currentOffspring.UniqueID;
                        } 
                        else
                        {
                            idIncrement = currentOffspring.UniqueID.Substring(parentOffspring.UniqueID.Length + 1);
                            idIncrement = idIncrement.Substring(idIncrement.IndexOf(IdSeparator) + 1);                                  
                        }                                                 

                        clientIdParts.Insert(0, new List<string>(idIncrement.Split(IdSeparator)));                        

                        if (currentOffspring is Root)
                        {
                            break;
                        }

                        currentOffspring = parentOffspring;
                    }
                }

                return clientIdParts;
            }
        }

        private string NamesListKey
        {
            get
            {
                return String.Join("/", NamesList.ToArray());
            }
        }

        internal void CreatePrototypeData()
        {            
            if (Root == null || Root.PrototypeDescriptors.ContainsKey(NamesListKey))
            {
                return;
            }
            
            Owner.AddPrototypeItem(UniqueId, ClientId);
            EnsurePrototypeDescriptor();            
        }

        private void EnsurePrototypeDescriptor()
        {
            if (Root.PrototypeDescriptors.ContainsKey(NamesListKey))
            {
                return;
            }

            Root.PrototypeDescriptors[NamesListKey] = CreatePrototypeDescriptor();
        }

        private ScriptComponentDescriptor CreatePrototypeDescriptor()
        {
            var descriptor = new ScriptComponentDescriptor("MBasis");                       
            descriptor.AddProperty("rootId", Owner.Root.ClientID);
            descriptor.AddProperty("id", ClientId);
            descriptor.AddProperty("minOccurs", Owner.MinOccurs);
            descriptor.AddProperty("maxOccurs", Owner.MaxOccurs);
            descriptor.AddProperty("last", Owner is Leaf);
            return descriptor;
        }
    }
}
